/*******************************************************************************
* This class is used to open v4l2 cameras. It uses v4l2 libraries for video
* files.
* 
*
* 
*
* Licensed under GPL Version 3 license (/license.txt).
* Author: Eder A. Perez (eder.perez@ice.ufjf.br)
*******************************************************************************/

#ifndef __CV_V4L2_HANDLER__
#define __CV_V4L2_HANDLER__

#include "cvdatatypes.h"
#include "cverror.h"
#include <linux/videodev2.h>


// Supported formats for retrieving
typedef enum {

  CV_RETRFMT_DEFAULT = 0,
  CV_RETRFMT_RGB24,
  CV_RETRFMT_GREY8,
  CV_RETRFMT_GREY24
  
} CVv4l2_retrfmt_t;


// Supported formats for device
typedef enum {
  
  CV_V4L2_DEVFMT_DEFAULT = 0,
  CV_V4L2_DEVFMT_RGB332  = V4L2_PIX_FMT_RGB332,
  CV_V4L2_DEVFMT_RGB555  = V4L2_PIX_FMT_RGB555,
  CV_V4L2_DEVFMT_RGB565  = V4L2_PIX_FMT_RGB565,
  CV_V4L2_DEVFMT_RGB24   = V4L2_PIX_FMT_RGB24,
  CV_V4L2_DEVFMT_RGB32   = V4L2_PIX_FMT_RGB32,
  CV_V4L2_DEVFMT_GREY    = V4L2_PIX_FMT_GREY,
  CV_V4L2_DEVFMT_YUYV    = V4L2_PIX_FMT_YUYV
  
} CVv4l2_devfmt_t;



// V4L2 parameters structure
typedef struct __v4l2_params {
  int width;
  int height;
  int fps;
  CVv4l2_retrfmt_t retrieve_fmt;  // This is the format retrieved by getFrame()
  CVv4l2_devfmt_t  device_fmt;    // This is the format used by the device
} CVv4l2params_t;



class CVVideoV4L2 {

  /**********************
  *      ATTRIBUTES     *
  **********************/

  public:
    // Format attributes
    unsigned int width;
    unsigned int height;
    float        fps;
    unsigned int bpp;      // Bits per pixel in retrieved data

    // For error handle
    CVerror_t errorcode;

  private:
    CVubyte  *buffer;        // Store a frame grabbed
    CVuint32 buffsize;       // Number of bytes allocated for buffer
    bool input_opened;       // True if a v4l2 device is already opened
    
    // V4L2 devices attributes
    int              fd;           // File descriptor of opened camera device
    v4l2_capability  capability;
    v4l2_input       input;
    v4l2_buffer      bf;
    int              read_type;    // The buffer read can be done by read() function ou memory map
    CVuint32         pixelformat;  // Current pixel format
    CVv4l2_retrfmt_t retrieve_fmt; // Format retrieved by getFrame (RGB, YUV or GREY)
    int              rowsize;      // Number of bytes per line in an image



  /**********************
  *       METHODS       *
  **********************/
  
  public:
    // Constructors
    CVVideoV4L2();
    ~CVVideoV4L2();
    
    bool openV4L2(const char* device, CVv4l2params_t params);
    bool getFrame(CVubyte* data); // Copies the current frame to data

  private:
    // V4L2 devices methods
    bool init_v4l2_camera(CVv4l2params_t params);
    bool get_frame_v4l2read(CVubyte* data); // Retrieve data using read() function
    bool get_frame_v4l2strm(CVubyte* data); // Retrieve data using memory mapping
    //int  getCurrentFormat();
    //bool setPxlFormat(const int fmt);
    
    // General private methods
    bool (CVVideoV4L2::*get_frame_ptr)(CVubyte*); // Points to the correct get frame method
    int  getBpp(CVuint32 pxlfmt);             // Return bpp based on v4l2_pix_format
    
    // Methods to convert pixel data
    void set_conv_function();
    void (CVVideoV4L2::*convert_buffer_data)(CVubyte*);
    void YUYV_to_RGB24(CVubyte* data);
    void YUYV_to_GREY8(CVubyte* data);
    void YUYV_to_GREY24(CVubyte* data);

};

#endif

